/*
 * Copyright 2007-2010 Jeremy Brown.
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @author <a href="http://jeremy-brown.com">Jeremy Brown</a>
 */


package groovy.prefuse.factory

import prefuse.data.query.*

public class QueryBindingFactory extends AbstractFactory
{
	private Class klass

	public QueryBindingFactory()
	{
	}
	
	public QueryBindingFactory(Class klass)
	{
		this.klass = klass
	}

	boolean isLeaf()
	{
		return false
	}
	    
    public Object newInstance(FactoryBuilderSupport builder, Object name, Object value, Map attributes) throws InstantiationException, IllegalAccessException
	{
		//SearchQueryBinding takes tupleSet:, field:, (and searchTupleSet:)
		//RangeQueryBinding takes tupleSet:, field:, (and forceOrdinal:)
		//ListQueryBinding takes tupleSet:, field:, (and includeAllOption:)

		if(value == null && attributes.action)
		{
			value = attributes.remove("action")
		}
		
		if(value instanceof DynamicQueryBinding)
		{
			return value
		}
		
		def buildClass
		if(klass)
		{
			buildClass = klass
		}
		else if(value instanceof Class)
		{
			buildClass = value
			value = null
		}

		
		def queryBinding = null

		if(buildClass instanceof Class && DynamicQueryBinding.isAssignableFrom(buildClass))
		{
			def tupleSet = attributes.remove("tupleSet")
			def field = attributes.remove("field")
			
			if(ListQueryBinding.equals(buildClass))
			{
				if(attributes.includeAllOption != null)
				{
					queryBinding = new ListQueryBinding(tupleSet, field, attributes.remove("includeAllOptions"))
				}
				else
				{
					queryBinding = new ListQueryBinding(tupleSet, field)
				}
			}
			else if(RangeQueryBinding.equals(buildClass))
			{
				if(attributes.forceOrdinal)
				{
					queryBinding = new RangeQueryBinding(tupleSet, field, attributes.remove("forceOrdinal"))
				}
				else
				{
					queryBinding = new RangeQueryBinding(tupleSet, field)
				}
				
				//handle the optional valueRange: attribute
				if(attributes.valueRange != null)
				{
					def valueRange = attributes.remove("valueRange")
					def model = queryBinding.getModel()
					if(model instanceof NumberRangeModel)
					{
						//valueRange should be a list of 4 numbers [low, high, min, max]
						model.setValueRange(*valueRange)
					}
					else if(model instanceof ObjectRangeModel)
					{
						//valueRange should be a list of objects [object, object, object,...]
						model.setValueRange(valueRange)
					}
				}
			}
			else if(SearchQueryBinding.equals(buildClass))
			{
				if(attributes.searchTupleSet)
				{
					queryBinding = new SearchQueryBinding(tupleSet, field, attributes.remove("searchTupleSet"))
				}
				else
				{
					queryBinding = new SearchQueryBinding(tupleSet, field)
				}
			}
			else
			{
				//Try to instantiate the Action with a no-parameter-constructor
				queryBinding = buildClass.newInstance()
			}
		}

		return queryBinding
	}
}
